/**
 * @(#)SystemHistoryProcessInstanceServiceImpl.java Dec 10, 2009
 *   
 * Copyright  (c) 2009-2010 Wilmar IT Service,  Inc.   
 * All  rights  reserved.   
 * TODO
 */

package com.wilmar.process.core.services.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jbpm.api.ProcessEngine;
import org.jbpm.api.ProcessInstance;
import org.jbpm.api.history.HistoryProcessInstance;

import com.wilmar.process.core.services.api.ISystemHistoryProcessInstanceService;
import com.wilmar.process.core.services.api.ISystemProcessLogService;
import com.wilmar.process.dao.api.IHistoryProcessInstanceQueryDAO;
import com.wilmar.process.entity.ProcessLog;
import com.wilmar.process.entity.User;
import com.wilmar.process.entity.query.HistoryProcessInstanceQueryObject;
import com.wilmar.process.entity.query.ProcessLogQueryObject;
import com.wilmar.process.entity.vo.HistoryProcessInstanceVO;
import com.wilmar.process.entity.vo.ProcessLogVO;
import com.wilmar.process.enumerate.EnumProcessInstanceState;
import com.wilmar.process.exception.ObjectNotFoundException;

/**
 * @author MaKuBEX Email:makubexnet@gmail.com
 * @version 1.0.0
 */
public class SystemHistoryProcessInstanceServiceImpl implements
		ISystemHistoryProcessInstanceService {

	private ProcessEngine processEngine;
	private ISystemProcessLogService systemProcessLogService;
	private IHistoryProcessInstanceQueryDAO historyProcessInstanceQueryDAO;

	/**
	 * @see com.wilmar.process.core.services.api.ISystemHistoryProcessInstanceService#getListUsersCommitedProcessInstance(com.wilmar.process.entity.User,
	 *      com.wilmar.common.util.PageinationEntity)
	 */
	public List<HistoryProcessInstanceVO> getListUsersCommitedProcessInstance(
			User user, HistoryProcessInstanceQueryObject prototype) {
		List<HistoryProcessInstance> historyList = new ArrayList<HistoryProcessInstance>();
		List<ProcessLog> startLogList = null;
		if (prototype != null) {
			ProcessLogQueryObject logPrototype = new ProcessLogQueryObject();
			logPrototype.setProcessDefinitionKey(prototype
					.getProcessDefinitionKey());
			logPrototype.setMaxEnterTime(prototype.getMaxStartTime());
			logPrototype.setMinEnterTime(prototype.getMinStartTime());
			logPrototype.setPageination(prototype.getPageination());
			logPrototype.setProcessDefinitionName(prototype
					.getProcessDefinitionName());
			logPrototype.setProcessInstanceId(prototype.getProcessInstanceId());
			startLogList = this.systemProcessLogService
					.getListOnlyStartRecordByUser(user, logPrototype);
		}
		Set<String> piidSet = new HashSet<String>();
		List<HistoryProcessInstance> hisList = new ArrayList<HistoryProcessInstance>();
		for (int index = 0; index < startLogList.size(); index++) {
			if (index > 0 && index % 900 == 0) {
				hisList.addAll(this.historyProcessInstanceQueryDAO
						.getListByProcessInstanceId(piidSet));
				piidSet.clear();
			}
			ProcessLog startLog = startLogList.get(index);
			piidSet.add(startLog.getProcessInstanceId());
		}
		if (!piidSet.isEmpty())
			hisList.addAll(this.historyProcessInstanceQueryDAO
					.getListByProcessInstanceId(piidSet));
		for (HistoryProcessInstance hpi : hisList) {
			boolean flag = true;
			if (prototype.getState() != null) {
				flag = false;
				for (EnumProcessInstanceState s : prototype.getState()) {
					if (s.getState().equalsIgnoreCase(hpi.getState()))
						flag = true;
				}
			}
			if (flag && hpi != null)
				historyList.add(hpi);
		}
		List<HistoryProcessInstanceVO> result = new ArrayList<HistoryProcessInstanceVO>();
		if (historyList != null && !historyList.isEmpty())
			result = this.convertToVOList(historyList);
		return result;
	}

	/**
	 * 
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVO(java.lang
	 *      .Object)
	 */
	public HistoryProcessInstanceVO convertToVO(HistoryProcessInstance entity) {
		ProcessLog startLog = null;
		try {
			startLog = this.systemProcessLogService
					.getDetailOnlyStartRecordByProcessInstanceId(entity
							.getProcessInstanceId());
		} catch (ObjectNotFoundException e) {
			e.printStackTrace();
		}
		ProcessInstance pi = this.processEngine.getExecutionService()
				.findProcessInstanceById(entity.getProcessInstanceId());
		HistoryProcessInstanceVO vo = new HistoryProcessInstanceVO(entity, pi,
				this.systemProcessLogService.convertToVO(startLog));
		return vo;
	}

	public List<HistoryProcessInstanceVO> convertToVOList(
			List<HistoryProcessInstance> entityList,
			List<ProcessLog> startLostList) {
		List<HistoryProcessInstanceVO> hpiList = new ArrayList<HistoryProcessInstanceVO>(
				entityList.size());
		Map<String, ProcessLogVO> logVOMap = new HashMap<String, ProcessLogVO>();
		for (ProcessLog log : startLostList) {
			logVOMap.put(log.getProcessInstanceId(), new ProcessLogVO(log));
		}
		for (HistoryProcessInstance hpi : entityList) {
			hpiList.add(new HistoryProcessInstanceVO(hpi, logVOMap.get(hpi
					.getProcessInstanceId())));
		}
		return hpiList;
	}

	/**
	 * 
	 * @see com.wilmar.process.core.services.api.IBaseService#convertToVOList(java
	 *      .util.List)
	 */
	public List<HistoryProcessInstanceVO> convertToVOList(
			Collection<HistoryProcessInstance> entityCollection) {
		List<HistoryProcessInstanceVO> voList = new ArrayList<HistoryProcessInstanceVO>(
				entityCollection.size());
		for (HistoryProcessInstance his : entityCollection) {
			voList.add(this.convertToVO(his));
		}
		return voList;
	}

	/**
	 * @return the systemProcessLogService
	 */
	public ISystemProcessLogService getSystemProcessLogService() {
		return systemProcessLogService;
	}

	/**
	 * @param systemProcessLogService
	 *            the systemProcessLogService to set
	 */
	public void setSystemProcessLogService(
			ISystemProcessLogService systemProcessLogService) {
		this.systemProcessLogService = systemProcessLogService;
	}

	/**
	 * @see com.wilmar.process.core.services.api.ISystemHistoryProcessInstanceService#getDetailById(java.lang.String)
	 */
	public HistoryProcessInstance getDetailById(String processInstanceId)
			throws ObjectNotFoundException {
		HistoryProcessInstance historyProcessInstance = this.processEngine
				.getHistoryService().createHistoryProcessInstanceQuery()
				.processInstanceId(processInstanceId).uniqueResult();
		if (historyProcessInstance == null)
			throw new ObjectNotFoundException(
					"There is no history process instance's id is:"
							+ processInstanceId);
		return historyProcessInstance;
	}

	/**
	 * @return the processEngine
	 */
	public ProcessEngine getProcessEngine() {
		return processEngine;
	}

	/**
	 * @param processEngine
	 *            the processEngine to set
	 */
	public void setProcessEngine(ProcessEngine processEngine) {
		this.processEngine = processEngine;
	}

	/**
	 * @return the historyProcessInstanceQueryDAO
	 */
	public IHistoryProcessInstanceQueryDAO getHistoryProcessInstanceQueryDAO() {
		return historyProcessInstanceQueryDAO;
	}

	/**
	 * @param historyProcessInstanceQueryDAO
	 *            the historyProcessInstanceQueryDAO to set
	 */
	public void setHistoryProcessInstanceQueryDAO(
			IHistoryProcessInstanceQueryDAO historyProcessInstanceQueryDAO) {
		this.historyProcessInstanceQueryDAO = historyProcessInstanceQueryDAO;
	}
}
